package com.zmn.oms.dubbo.impl.statistics;

import com.alibaba.fastjson.JSON;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dio.normal.statistics.EngineerOrderStatDIO;
import com.zmn.oms.common.dro.statistics.EngineerOrderStatDRO;
import com.zmn.oms.dubbo.interfaces.statistics.StatOrderEngineerRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.validation.annotation.Validated;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 类描述:
 *
 * @author: HuangChao
 * @since: 2022/08/16 16:21
 */
@Slf4j
@DubboService(loadbalance = "roundrobin", timeout = 10000, retries = 2, version = DubboConsts.INTERFACE_VERSION)
public class StatOrderEngineerRemoteServiceImpl implements StatOrderEngineerRemoteService {

    @Autowired
    private OrderWorkEsBService orderWorkEsBService;

    @Override
    public ResponseDTO<List<EngineerOrderStatDRO>> getOrderStatByQuery(@Validated EngineerOrderStatDIO dio) {
        log.info("批量查询工程师订单入参：{}", dio);
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termsQuery("masterId", dio.getEngineerIdList()))
                .filter(QueryBuilders.termQuery("isTest", false));
        String groupFiled = "masterId";
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery build = nativeSearchQueryBuilder
                .withQuery(queryBuilder)
                .withPageable(Pageable.unpaged())
                .build();

        // 工程师分组
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(groupFiled)
                .field(groupFiled).size(10000);
        // 进行中工单数量
        termsAggregationBuilder.subAggregation(AggregationBuilders.filter("doingCount", QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING))));
        // 指定时间内的领单数量
        termsAggregationBuilder.subAggregation(AggregationBuilders.filter("takeCount", QueryBuilders.boolQuery()
                .filter(QueryBuilders.rangeQuery("takeTime").from(dio.getStartDate()).to(dio.getEndDate()))));

        build.addAggregation(termsAggregationBuilder);

        Aggregations query = orderWorkEsBService.getAggregationsByQuery(build);

        if (log.isDebugEnabled()) {
            log.debug("es-统计入参：{}", JSON.toJSONString(build));
            log.debug("es-统计出参：{}", JSON.toJSONString(query));
        }

        ParsedTerms terms = query.get(groupFiled);
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        if (CollectionUtils.isEmpty(buckets)) {
            return ResponseDTO.success(Collections.emptyList());
        }

        List<EngineerOrderStatDRO> statDROList = buckets.stream()
                .filter(bucket -> Objects.nonNull(bucket.getKeyAsNumber()))
                .map(bucket -> {
                    EngineerOrderStatDRO statDRO = new EngineerOrderStatDRO();
                    statDRO.setEngineerId(bucket.getKeyAsNumber().intValue());
                    Aggregations dataAgg = bucket.getAggregations();
                    Long doingCount = ((ParsedFilter) dataAgg.get("doingCount")).getDocCount();
                    statDRO.setDoingCount(doingCount);
                    Long takeCount = ((ParsedFilter) dataAgg.get("takeCount")).getDocCount();
                    statDRO.setTakeCount(takeCount);
                    return statDRO;
                }).collect(Collectors.toList());

        return ResponseDTO.success(statDROList);
    }
}
